using GameBaseFramework.Extension;
using GameBaseFramework.Timer;
using GameLogic.AbilitySystem.Attribute;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace GameLogic.AbilitySystem.Effect
{
    /// <summary>
    /// Buff管理器-管理附加在AbilitySystemComponent上的Buff类
    /// </summary>
    public class EffectContainer
    {
        /// <summary>
        /// 作用于的数值集
        /// </summary>
        public AttributeSet TargetAttributeSet;

        /// <summary>
        /// Tag到Effect的映射
        /// </summary>
        private Dictionary<string, List<ActiveEffect>> TagsEffectDic = new();

        /// <summary>
        /// Effect的列表
        /// 只保存lasting
        /// </summary>
        private List<ActiveEffect> LastingEffectList = new();

        /// <summary>
        /// Effect的列表
        /// 只保存Duration
        /// </summary>
        private List<ActiveEffect> DurationEffectList = new();

        /// <summary>
        /// 添加Buff
        /// </summary>
        /// <returns></returns>
        public void AddEffect(EffectBase effect, float mul = 1.0f)
        {
            switch (effect.ModifyType)
            {
                case (EffectModifyType.Instance):
                    {
                        //立即生效的Effect无需保存，直接施加在Base上
                        TargetAttributeSet.InstanceApply(effect.InstanceAttribute);
                        break;
                    }
                case (EffectModifyType.Lasting):
                    {
                        ActiveEffect activeEffect = new ActiveEffect
                        {
                            effect = effect,
                            RemainingTime = effect.LastingTime
                        };

                        LastingEffectList.Add(activeEffect);
                        AddEffectToDic(activeEffect);
                        RefreshMergeEffect();
                        break;
                    }
                case (EffectModifyType.Duration):
                    {
                        ActiveEffect activeEffect = new ActiveEffect
                        {
                            effect = effect,
                            RemainingTime = effect.LastingTime,
                            NextActivateTime = effect.TimeDelta,
                            mul = mul
                        };
                        DurationEffectList.Add(activeEffect);
                        AddEffectToDic(activeEffect);
                        break;
                    }
            }
        }


        /// <summary>
        /// 把effect加入到字典中去
        /// </summary>
        /// <param name="effect"></param>
        private void AddEffectToDic(ActiveEffect effect)
        {
            if (!effect.effect.Tags.IsNullOrEmpty())
            {
                foreach (var i in effect.effect.Tags)
                {
                    List<ActiveEffect> list;
                    if (TagsEffectDic.TryGetValue(i, out list))
                    {
                        list.Add(effect);
                    }
                    else
                    {
                        list = new() { effect };
                        TagsEffectDic.Add(i, list);
                    }
                }
            }
        }

        /// <summary>
        /// 重新计算当前buff的总效果
        /// </summary>
        private void RefreshMergeEffect()
        {
            LastingEffectAttribute mergedLastingEffectAttribute = new LastingEffectAttribute();

            foreach (var i in LastingEffectList)
            {
                mergedLastingEffectAttribute.Merge(i.effect.LastingEffectAttribute);
            }

            TargetAttributeSet.ApplyLasting(mergedLastingEffectAttribute);
        }


        /// <summary>
        /// 移除带有指定Tag的Effect
        /// 处理字典方面
        /// </summary>
        /// <param name="tag"></param>
        public void RemoveEffectWithTag(string tag)
        {
            if (TagsEffectDic.TryGetValue(tag, out var list))
            {
                if (!list.IsNull())
                {
                    foreach (var i in list)
                    {
                        RemoveEffect(i);
                    }
                    TagsEffectDic.Remove(tag);
                }
            }
        }

        /// <summary>
        /// 清除所有的Effect
        /// </summary>
        public void RemoveAllEffect()
        {
            LastingEffectList.Clear();
            DurationEffectList.Clear();
            TagsEffectDic.Clear();
            RefreshMergeEffect();
        }

        /// <summary>
        /// 移除Effect 处理List方面
        /// </summary>
        /// <param name="effect"></param>
        public void RemoveEffect(ActiveEffect effect)
        {
            if (effect.effect.ModifyType == EffectModifyType.Duration)
            {
                DurationEffectList.Remove(effect);
            }
            else
            {
                LastingEffectList.Remove(effect);
            }
            RefreshMergeEffect();
        }

        /// <summary>
        /// 驱动函数
        /// </summary>
        public void Update(float DeltaTime)
        {
            UpdateLastingEffect(DeltaTime);
            UpdateDurationEffect(DeltaTime);
        }

        /// <summary>
        /// 更新间隔效果
        /// </summary>
        private void UpdateDurationEffect(float DeltaTime)
        {
            foreach (var i in DurationEffectList)
            {
                i.RemainingTime -= DeltaTime;

                if (i.RemainingTime < 0)
                {
                    RemoveEffect(i);
                    continue;
                }

                i.NextActivateTime -= DeltaTime;
                while (i.NextActivateTime < 0)
                {
                    i.NextActivateTime += i.effect.TimeDelta;
                    TargetAttributeSet.InstanceApply(i.effect.InstanceAttribute);
                }
            }
        }

        /// <summary>
        /// 更新持续效果
        /// </summary>
        private void UpdateLastingEffect(float DeltaTime)
        {
            foreach (var i in LastingEffectList)
            {
                i.RemainingTime -= DeltaTime;
                if (i.RemainingTime < 0)
                {
                    RemoveEffect(i);
                }
            }
        }
    }
}
